<?php
/**
 *  NevuxBB - Free Forum Software
 *  Copyright (C) 2008, 2010 NevuxBB (No one specific author)*  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * NevuxBB (Kernel) Base System
 * File: base_class.php
 *
 */

class KernelBaseSystem {
	
	/**
	* Used to display a fatal error page
	*
	* @param string $errdesc
	* @param string $errfile
	* @param string $errline
	* @return void
	* @access private
	*/		
	private function displayFatalError($errdesc, $errfile, $errline) {
		// large collection of HTML code to produce the error page
		echo('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
		<html xmlns="http://www.w3.org/1999/xhtml">
		<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>NevuxBB, Fatal Error</title>
		<style type="text/css">
		<!--
		body,td,th {
			font-family: Verdana, Geneva, sans-serif;
			font-size: 12px;
		}
		body {
			background-color: #243649;
		}
		h1 {
			color: #910003;
			text-align: center;
		}
		.copyright {
			color: #FFF;
		}
		-->
		</style></head>
		<body>
		<table width="600" border="0" cellspacing="0" cellpadding="15" align="center">
		  <tr>
			<td bgcolor="#FFFFFF" colspan="2"><h1><strong>A fatal error</strong> has occoured!</h1><br /><br />Unfortunately a fatal error occurred, the kernel has stopped the system from continuing to execute the software to prevent damage to your system. More details about this error can be viewed below; due to the extreme circumstances of the problem this error has not been logged in the system as the communication to other code has been stopped.<br /><br /><strong>Debug:</strong><br /><br /><strong>File:</strong> ' . $errfile . '<br /><strong>Line:</strong> ' . $errline . '<br /><strong>Description:</strong> ' . $errdesc . '<br /></td>
		  </tr>
		  <tr>
			<td align="center" class="copyright">&copy; Copyright 2008 - 2009 NevuxBB</td>
			<td align="center"><img src="templates/Vram/images/transparent_footer_logo.png" width="133" height="54" /></td>
		  </tr>
		</table>
		</body>
		</html>');
	}
	
	/**
	* Used to handle some script errors
	*
	* @param string $errno
	* @param string $errstr
	* @param string $errfile
	* @param string $errline
	* @return boolean
	* @access public (static)
	*/		
	public static function nbbErrorSystem($errno, $errstr, $errfile, $errline) {
		// pass error type
		switch ($errno) {
			case E_USER_ERROR:
				// is a requested fatal error, show fatal error page
				self::displayFatalError($errstr, $errfile, $errline);
				
				// kill the script
				exit(1);
				break;
			case E_USER_WARNING:
				// attempt to log these to the database
				if(method_exists('Db_Abstraction', 'query')) {
					// does exist, log it
					// get actual file
					$new_file_name = end(explode('/', $errfile));
					$new_file_name = end(explode('\\', $new_file_name));
					
					// piece the strings together
					$data = Db_Abstraction::clean($errstr . ' (Line ' . $errline . ' in file ' . $new_file_name . ')');
					
					// update the database
					Db_Abstraction::query("INSERT INTO `nbb_error_reports` (`err_data`, `err_sent`) VALUES ('$data', '0')");
				} else {
					/*** failed to log
							a) error occured with db abstraction class
							b) error triggered before db abstraction class was loaded?
							c) error was too severe
					***/
				}
				
				// break
				break;
			case E_USER_NOTICE:
				// attempt to log these to the database
				if(method_exists('Db_Abstraction', 'query')) {
					// does exist, log it
					// get actual file
					$new_file_name = end(explode('/', $errfile));
					$new_file_name = end(explode('\\', $new_file_name));
					
					// piece the strings together
					$data = Db_Abstraction::clean($errstr . ' (Line ' . $errline . ' in file ' . $new_file_name . ')');
					
					// update the database
					Db_Abstraction::query("INSERT INTO `nbb_error_reports` (`err_data`, `err_sent`) VALUES ('$data', '0')");
				} else {
					/*** failed to log
							a) error occured with db abstraction class
							b) error triggered before db abstraction class was loaded?
							c) error was too severe
					***/
				}
				
				// break
				break;
			default:
				// these errors shouldn't be logged, too vague and too many
				// perhaps add more specific case paramaters
				break;
		}
		
		// return true
		return true;
	}
	
	/**
	* Used to fetch physical files
	*
	* @param string $file
	* @return anything
	* @access public
	*/
	public function fetchFile($file) {
		// attempt to open the file with file_get_contents
		$file_contents = file_get_contents($file);
		
		if($file_contents === false) {
			// attempt to file it
			$file_contents = file($file);
			
			// did this attempt work?
			if($file_contents === false) {
				// just can't open this file
				trigger_error('<strong>Kernel Failure:</strong> Unable to open the file for read (' . $file . ')', E_USER_WARNING);
				
				// return false, can't open it
				return false;
			} else {
				// return contents
				#var_dump($file_contents);
				return $file_contents;
			}
		} else {
			// return contents
			#var_dump($file_contents);
			return $file_contents;
		}
	}
	
	/**
	* Used to remove files on request
	*
	* @param string $file
	* @return boolean
	* @access public
	*/	
	public function removeFile($file) {
		if(unlink($file)) {
			// removed
			return true;
		} else {
			// not removed, trigger logging
			trigger_error('<strong>Kernel Failure:</strong> Unable to remove the file (' . $file . ')', E_USER_WARNING);
			
			// tell the class it can't be done
			return false;
		}
	}
	
	/**
	* Used to write data into files
	*
	* @param string $file
	* @param string $data
	* @return boolean
	* @access public
	*/	
	public function writeFile($file, $data) {
		// begin writing the file
		$fh = fopen($file, 'w');
		
		// did it create the file?
		if($fh === false) {
			// afraid not, trigger logging
			trigger_error('<strong>Kernel Failure:</strong> Unable to write the new file (' . $file . ')', E_USER_WARNING);
			
			// tell the class it can't be done
			return false;
		} else {
			// did work, which is always good
			fwrite($fh, $data);
			fclose($fh);
			
			// success!
			return true;
		}
	}
	
	/**
	* Used to rename files
	*
	* @param string $file
	* @param string $new_file_name
	* @param string $forcewrite
	* @return boolean
	* @access public
	*/	
	public function renameFile($file, $new_file_name, $forcewrite = NULL) {
		// is this file writable?
		if(is_writable($file)) {
			// is writable anyway, proceed with rename
			if(rename($file, $new_file_name)) {
				// rename was successful
				return true;
			} else {
				// failed to rename, odd
				return false;
			}
		} else {
			// isn't writeable, should we force it?
			if($forcewrite) {
				// force it
				if(chmod($file, 0600)) {
					// chmod worked, is it now writable?
					// clear cache first
					clearstatcache();
					
					// now check
					if(is_writable($file)) {
						// is now writable
						if(rename($file, $new_file_name)) {
							// rename was successful
							return true;
						} else {
							// failed to rename, odd
							return false;
						}
					} else {
						// failed
						return false;
					}
				} else {
					// failed to chmod, attempt to chown
					if(chown($file, 'www-data')) {
						// worked, is it now writable?
						// clear cache first
						clearstatcache();
						
						// now check
						if(is_writable($file)) {
							// is writable
							if(rename($file, $new_file_name)) {
								// rename was successful
								return true;
							} else {
								// failed to rename, odd
								return false;
							}
						} else {
							// isn't, failed
							return false;
						}
					} else {
						// failed, return false;
						return false;
					}
				}
			} else {
				// failed
				return false;
			}
		}
	}
	
	/**
	* Used to copy files
	*
	* @param string $filename
	* @param string $new_name
	* @return boolean
	* @access public
	*/	
	public function copyFile($filename, $new_name) {
		// we need to get the current directory of the
		// filename only
		$new_file_name = explode('\\', $filename);
		$new_file_name = implode('/', $new_file_name);
		$new_file_name = explode('/', $new_file_name);

		// remove the filename
		array_pop($new_file_name);

		// put it back together
		$location = implode('/', $new_file_name);
		
		// extract the file name of, $new_name, only
		$new_newname = explode('\\', $new_name);
		$new_newname = implode('/', $new_newname);
		$new_newname = explode('/', $new_newname);
		$new_f_name = end($new_newname);
		
		// begin to copy that file to the new name
		if(copy($filename, $location . '/' . $new_f_name)) {
			// has succeeded
			return true;
		} else {
			// return false, failed
			return false;
		}
	}
	
	/**
	* Used to fetch web files
	*
	* @param string $url
	* @return boolean
	* @access public
	*/	
	private function fetchWebFileMethods($method, $url) {
		switch($method) {
			case 1:
				// method one, CURL
				if(function_exists('curl_init')) {
					// curl is installed on this system
					$ch = curl_init($url);
					
					// configure settings
					curl_setopt($ch, CURLOPT_HEADER, 0);
					curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
					curl_setopt($ch, CURLOPT_USERAGENT, 'nevuxbb');
					curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
					
					// execute and close
					$data = curl_exec($ch);
					curl_close($ch);
					
					// return
					return $data;
				} else {
					// failed, try another method (non-preffered)
					self::fetchWebFileMethods(2, $url);
				}
				
				// break
				break;
			case 2:
				// file_get_contents
				$settings = stream_context_create(array('http' => array('timeout' => 5)));
				$data = file_get_contents($url, 0, $settings);
				
				if($data === false) {
					// failed to obtain file
					return false;
				} else {
					// success, return data
					return $data;
				}
				
				// break
				break;
			default:
				// no method?
				return false;
				break;
		}
	}
	
	/**
	* Used to fetch web files
	*
	* @param string $url
	* @return boolean
	* @access public
	*/	
	public function fetchWebFile($url) {
		// get setting
		$data = GlobalSettings::getSetting('pref_web_get_method');
		
		// does the setting exist?
		if(isset($data)) {
			// got a preferred method
			return self::fetchWebFileMethods($data, $url);
		} else {
			// go for default, 1
			return self::fetchWebFileMethods(1, $url);
		}
	}
	
	/**
	* Used to flush the buffer
	*
	* @access public
	*/	
	public function FlushBuffer() {
		// flushes the buffer
		ob_end_flush(); 
		ob_flush(); 
		flush(); 
		ob_start(); 
	}
}

// make sure the kernel handles most error requests
set_error_handler(array("KernelBaseSystem", "nbbErrorSystem"), E_ALL);
?>